//==========================================================================//
//                                                                          //
//  SHT11 Library               Version 0.1                     March 2012  //
//                                                                          //
//  Written for the Arduino Duemilanove w/ ATmega328                        //
//                                                                          //
//  SHT11 Arduino Library                                                   //
//                                                                          //
//  Created by JFLagarde (jeanfrancoislagarde@hotmail.com)                  //
//                                                                          //
//  This file is part of OpenWS (http://code.google.com/p/openws/)          //
//                                                                          //
//==========================================================================//
//                                                                          //
//  Notes:                                                                  //
//                                                                          //
//                                                                          //
//==========================================================================//
//                                                                          //
//  Copyright 2012 Jean-Francois Lagarde (jeanfrancoislagarde@hotmail.com)  //
//  This program is distributed under the terms of                          //
//  the GNU General Public License                                          //
//                                                                          //
//  This program is free software: you can redistribute it and/or modify    //
//  it under the terms of the GNU General Public License as published by    //
//  the Free Software Foundation, either version 3 of the License, or       //
//  (at your option) any later version.                                     //
//                                                                          //
//  This program is distributed in the hope that it will be useful,         //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
//  GNU General Public License for more details.                            //
//                                                                          //
//  You should have received a copy of the GNU General Public License       //
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                          //
//==========================================================================//

#include <SHT11.h>

SHT11::SHT11() {
	_shtData = 5;
	_shtClk = 6;
	
	_ioByte = 0;
	_ackBit = 0;
	_dly = 0;
	
    _lastTemperature = 0;
	_lastHumidity = 0;
}

void SHT11::init() {
	init(5,6);
}
void SHT11::init(int shtData, int shtClk) {
	_shtClk = shtClk;
	_shtData = shtData;

	pinMode(_shtClk, OUTPUT);        // Clock
	pinMode(_shtData, OUTPUT);        // Data
	digitalWrite(_shtClk, HIGH);     // Clock

	connectionReset();
}
void SHT11::read() {
	_lastTemperature = readTemperature();
	_lastHumidity = readHumidity(_lastTemperature);
}
int SHT11::getTemperature() {
	return _lastTemperature;
}
int SHT11::getHumidity() {
	return _lastHumidity;
}




void SHT11::softReset(void) {
	connectionReset();

	_ioByte = 0x1E; //RST_CMD
	_ackBit = 1;
	writeByte();
	delay(15);
}
void SHT11::connectionReset(void) {
	//--------------------------------------------------------------------  
	// connection reset: DATA-line=1 and at least 9 SCK cycles followed by start
	// 16 is greater than 9 so do it twice
	//      _____________________________________________________         ________
	// DATA:                                                     |_______|
	//          _    _    _    _    _    _    _    _    _        ___    ___
	// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |__|   |______

	shiftOut(_shtData, _shtClk, LSBFIRST, 0xff);
	shiftOut(_shtData, _shtClk, LSBFIRST, 0xff);
	start();
}
void SHT11::start(void) {
	//--------------------------------------------------------------------
	// generates a sensirion specific transmission start
	// This where Sensirion is not following the I2C standard
	//       _____         ________
	// DATA:      |_______|
	//           ___     ___
	// SCK : ___|   |___|   |______

	digitalWrite(_shtData, HIGH);     // Data pin high
	pinMode(_shtData, OUTPUT);
	digitalWrite(_shtClk,  HIGH);     // clock high
	digitalWrite(_shtData,  LOW);     // data low
	digitalWrite(_shtClk,   LOW);     // clock low
	digitalWrite(_shtClk,  HIGH);     // clock high
	digitalWrite(_shtData, HIGH);     // data high
	digitalWrite(_shtClk,  LOW);      // clock low
}





int SHT11::readTemperature() {
	int temp_degC = readData(0x03);
	temp_degC = (temp_degC/10)-400;
	return temp_degC;
}
int SHT11::readHumidity(int temp_degC) {
	int r_humid = readData(0x05);
	
	// Linear conversion
	float rh_lin = r_humid*r_humid*-0.000028 + r_humid*0.405 - 40; 
	// Temperature compensated RH
	int rh_true = (temp_degC * (r_humid*0.00008 + 0.01) + rh_lin); 
	if(rh_true>1000) rh_true=1000;       // deal with rh being outside
	if(rh_true<1) rh_true=1;       // a physical possible range
	
	return rh_true;
}












int SHT11::readData(int SHT_CMD) {
	int retVal;

	softReset();
	start();
	_ioByte = SHT_CMD;

	writeByte();          // Issue Command
	wait();                // wait for data ready
	_ackBit = 0;               // read first byte

	readByte();
	int msby;                  // process it as Most Significant Byte (MSB)
	msby = _ioByte;
	_ackBit = 1;

	readByte();          // read second byte
	retVal = msby;           // process result to combine MSB with LSB
	retVal = retVal * 0x100;
	retVal = retVal + _ioByte;
	
	if (retVal <= 0) retVal = 1;
	return retVal;
}
void SHT11::writeByte(void) {
	pinMode(_shtData, OUTPUT);
	shiftOut(_shtData, _shtClk, MSBFIRST, _ioByte);
	pinMode(_shtData, INPUT);
	digitalWrite(_shtData, LOW);
	digitalWrite(_shtClk, LOW);
	digitalWrite(_shtClk, HIGH);
	_ackBit = digitalRead(_shtData);
	digitalWrite(_shtClk, LOW);
}
void SHT11::readByte(void) {
	_ioByte = shiftIn();
	digitalWrite(_shtData, _ackBit);
	pinMode(_shtData, OUTPUT);
	digitalWrite(_shtClk, HIGH);
	digitalWrite(_shtClk, LOW);
	pinMode(_shtData, INPUT);
	digitalWrite(_shtData, LOW);
}
int SHT11::shiftIn(void) {
	int cwt = 0;
	byte bitmask = 128;
	while (bitmask >= 1) {
		digitalWrite(_shtClk, HIGH);
		cwt = cwt + bitmask * digitalRead(_shtData);
		digitalWrite(_shtClk, LOW);
		bitmask=bitmask/2;
	}
	return(cwt);
}
void SHT11::wait(void) {
	delay(5);
	_dly = 0;
	while (_dly < 600) {
		if (digitalRead(_shtData) == 0) _dly=2600;
		delay(1);
		_dly=_dly+1;
	}
}